<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title>进程、线程管理与调度</title>
  <style type="text/css">code{white-space: pre;}</style>
  <link rel="stylesheet" href="doc/linux-style.css" type="text/css" />
</head>
<body>
<div id="header">
<h1 class="title">进程、线程管理与调度</h1>
</div>
<div id="TOC">
<ul>
<li><a href="#进程线程管理与调度">进程、线程管理与调度</a><ul>
<li><a href="#进程">1. 进程</a></li>
<li><a href="#线程">2. 线程</a></li>
<li><a href="#进程调度">3. 进程调度</a></li>
<li><a href="#其他关键概念">4. 其他关键概念</a></li>
<li><a href="#调度器的演进">5. 调度器的演进</a></li>
</ul></li>
</ul>
</div>
<h1 id="进程线程管理与调度">进程、线程管理与调度</h1>
<h2 id="进程">1. 进程</h2>
<h3 id="简介">1.1 简介</h3>
<p>程序是存储在磁盘中的指令集合，而进程是正在执行的程序实例，是内核调度的基本单位。Linux内核中，进程和线程的实现是统一的，线程被看作是特殊的进程。</p>
<p>进程提供两种虚拟机制：虚拟处理器和虚拟内存。我们可以通过<code>current-&gt;comm</code>和<code>current-&gt;pid</code>来获取进程名和进程ID。</p>
<h3 id="进程描述符">1.2 进程描述符</h3>
<p>每个进程用<code>struct task_struct</code>结构体描述，包含进程状态、父子进程关系等信息。进程状态包括：</p>
<ul>
<li><code>TASK_RUNNING</code>：进程可执行</li>
<li><code>TASK_INTERRUPTIBLE</code>：可被信号唤醒的休眠状态</li>
<li><code>TASK_UNINTERRUPTIBLE</code>：不可被信号唤醒的休眠状态</li>
<li><code>__TASK_STOPPED</code>：进程停止执行</li>
<li><code>__TASK_TRACED</code>：被其他进程跟踪</li>
</ul>
<p>退出状态包括：</p>
<ul>
<li><code>EXIT_ZOMBIE</code>：进程已终止，等待父进程读取状态</li>
<li><code>EXIT_DEAD</code>：进程状态已被读取，即将被清理</li>
</ul>
<p>系统启动时创建的<code>init</code>进程（PID为1）是所有其他进程的祖先。</p>
<h3 id="进程创建和终结">1.3 进程创建和终结</h3>
<p>进程创建通过<code>fork()</code>、<code>vfork()</code>等系统调用实现。<code>fork()</code>为子进程创建新的地址空间，而<code>vfork()</code>不复制地址空间，效率更高。</p>
<p>进程终结时，会调用<code>exit()</code>系统调用，进程状态变为<code>EXIT_ZOMBIE</code>，等待父进程通过<code>wait4()</code>或<code>waitpid()</code>查询并清理。</p>
<h2 id="线程">2. 线程</h2>
<h3 id="创建线程">2.1 创建线程</h3>
<p>线程是进程内的独立执行单元，共享进程的资源。通过<code>clone()</code>系统调用创建线程，设置<code>CLONE_VM</code>、<code>CLONE_FS</code>等标志位实现资源共享。</p>
<h3 id="内核线程">2.2 内核线程</h3>
<p>内核线程运行在内核空间，没有独立的地址空间。通过<code>kthread_create()</code>创建内核线程，需要调用<code>wake_up_process()</code>唤醒才能运行。</p>
<h3 id="调试">2.3 调试</h3>
<p>通过编译运行示例程序，可以查看线程的执行情况。使用<code>ps -L -e -o pid,ppid,lwp,cmd</code>命令可以列出所有线程。</p>
<h2 id="进程调度">3. 进程调度</h2>
<h3 id="简介-1">3.1 简介</h3>
<p>进程调度器负责决定哪个进程在CPU上运行。Linux使用抢占式多任务模式，调度器可以根据需要挂起正在运行的进程。</p>
<h3 id="调度策略">3.2 调度策略</h3>
<p>Linux支持多种调度策略：</p>
<ul>
<li><code>SCHED_NORMAL</code>：普通调度策略</li>
<li><code>SCHED_FIFO</code>：先入先出实时调度策略</li>
<li><code>SCHED_RR</code>：轮转实时调度策略</li>
<li><code>SCHED_BATCH</code>：批处理调度策略</li>
<li><code>SCHED_IDLE</code>：空闲调度策略</li>
<li><code>SCHED_DEADLINE</code>：截止期限调度策略</li>
</ul>
<h3 id="调度器实现">3.3 调度器实现</h3>
<ul>
<li><strong>完全公平调度器（CFS）</strong>：使用红黑树管理就绪队列，根据进程的虚拟运行时间选择下一个运行的进程。CFS的目标是公平分配CPU资源。</li>
<li><strong>EEVDF调度器</strong>：选择虚拟截止时间最早的进程运行，适合延迟敏感的应用。</li>
</ul>
<h3 id="on和o1调度器">3.4 O(n)和O(1)调度器</h3>
<ul>
<li><strong>O(n)调度器</strong>：早期内核使用的调度算法，效率较低。</li>
<li><strong>O(1)调度器</strong>：引入优先级数组，提高了调度效率，但已被CFS取代。</li>
</ul>
<h2 id="其他关键概念">4. 其他关键概念</h2>
<ul>
<li><strong>休眠和唤醒</strong>：进程可以通过<code>wait_queue_entry</code>休眠，并通过<code>wake_up()</code>唤醒。</li>
<li><strong>多处理器平衡</strong>：在多CPU系统中，调度器需要平衡各CPU的运行队列，使用调度域管理CPU集合。</li>
<li><strong>硬实时</strong>：PREEMPT_RT补丁集为Linux内核提供了硬实时支持，已在2024年被合并到主线内核。</li>
</ul>
<h2 id="调度器的演进">5. 调度器的演进</h2>
<ul>
<li><strong>BFS调度器</strong>：由Con Kolivas开发，适合桌面交互应用，但未被合入主线内核。</li>
<li><strong>Extensible Scheduler Class</strong>：提供可扩展的调度器实现。</li>
</ul>
</body>
</html>
